package com.zzedu.integration.tencentcloudspeech.impl;

import com.alibaba.fastjson2.JSON;
import com.tencent.core.ws.Credential;
import com.tencent.core.ws.SpeechClient;
import com.tencent.soe.OralEvaluationListener;
import com.tencent.soe.OralEvaluationRequest;
import com.tencent.soe.OralEvaluationResponse;
import com.tencent.soe.OralEvaluator;
import com.zzedu.integration.oss.IOssClientService;
import com.zzedu.integration.oss.dto.FileInfoDTO;
import com.zzedu.integration.tencentcloudspeech.ISpeechService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
public class SpeechServiceImpl implements ISpeechService {
    /**
     * 智能口语评测示例
     */
    Logger logger = LoggerFactory.getLogger(SpeechServiceImpl.class);
    @Autowired
    Credential credential;
    @Autowired
    SpeechClient proxy;
    @Autowired
    IOssClientService ossClientService;

    final Pattern pattern = Pattern.compile("\\s");

    /**
     * @param fileInfoDTO 文件信息
     * @param text        单词文本
     * @param uid         用户id+"_"+记录id
     * @param sendTimeout 发送数据超时时间 毫秒
     * @param readTimeout 接受数据超时时间 毫秒
     */
    public OralEvaluationResponse processStream(FileInfoDTO fileInfoDTO, String text, String uid, Long callTimeout, Long connectTimeout, Long readTimeout, double scoreCoeff) {
        byte[] data = ossClientService.download(fileInfoDTO.getUrl());
        if (data == null) {
            return null;
        }
        // EvalMode 评测模式
        //0：单词/单字模式（中文评测模式下为单字模式）
        //1：句子模式
        //2：段落模式
        //3：自由说模式
        //4：单词音素纠错模式
        //5：情景评测模式
        //6：句子多分支评测模式
        //7：单词实时评测模式
        //8：拼音评测模式
        OralEvaluationRequest request = new OralEvaluationRequest();
        request.setVoiceId(uid);
        request.setVoiceFormat(2);
        request.setRefText(text);
        request.setServerEngineType("16k_en");
        request.setScoreCoeff(scoreCoeff);
        request.setEvalMode(0);
        request.setTextMode(0);
        request.setRecMode(1);
        try {
            text = text.trim();
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                request.setEvalMode(1);
            }
        } catch (Exception e) {
            request.setEvalMode(3);
            logger.error("单词空格检测失败,详细:"+e.getMessage());
        }
        logger.debug("voice_id:{}", request.getVoiceId());
        CompletableFuture<OralEvaluationResponse> completableFuture = new CompletableFuture<OralEvaluationResponse>();
        OralEvaluationListener listener = new OralEvaluationListener() {//tips：回调方法中应该避免进行耗时操作，如果有耗时操作建议进行异步处理否则会影响websocket请求处理
            @Override
            public void OnIntermediateResults(OralEvaluationResponse response) {//评测中回调
                logger.info("{} voice_id:{},{}", "OnIntermediateResults", response.getVoiceId(), JSON.toJSON(response));
            }

            @Override
            public void onRecognitionStart(OralEvaluationResponse response) {//首包回调
                logger.info("{} voice_id:{},{}", "onRecognitionStart", response.getVoiceId(), JSON.toJSON(response));
            }

            @Override
            public void onRecognitionComplete(OralEvaluationResponse response) {//识别完成回调 即final=1
                logger.info("{} voice_id:{},{}", "onRecognitionComplete", response.getVoiceId(), JSON.toJSON(response));
                completableFuture.complete(response);
            }

            @Override
            public void onFail(OralEvaluationResponse response) {//失败回调
                logger.info("{} voice_id:{},{}", "onFail", response.getVoiceId(), JSON.toJSON(response));
                completableFuture.complete(response);
            }

            @Override
            public void onMessage(OralEvaluationResponse response) {//所有消息都会回调该方法
                logger.info("{} voice_id:{},{}", "onMessage", response.getVoiceId(), JSON.toJSON(response));
            }
        };
        OralEvaluator oralEvaluator = null;
        try {
            oralEvaluator = new OralEvaluator(proxy, credential, request, listener);
            long currentTimeMillis = System.currentTimeMillis();
            oralEvaluator.start(connectTimeout * 1000);
            logger.info("SpeechService start latency : " + (System.currentTimeMillis() - currentTimeMillis) + " ms");
            oralEvaluator.write(data);
            currentTimeMillis = System.currentTimeMillis();
            oralEvaluator.stop(readTimeout * 1000);
            logger.info("SpeechService stop latency : " + (System.currentTimeMillis() - currentTimeMillis) + " ms");
            OralEvaluationResponse response = completableFuture.get(callTimeout, TimeUnit.SECONDS);
            return response;
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            if (oralEvaluator != null) {
                oralEvaluator.close(); //关闭连接
            }
        }
        return null;
    }

}
